<template>
	<!-- 公用的sku规格选择弹窗 （直接购买和加入购物车公用） -->
	<page-container :show="sku_popup.show" position="bottom" @enter="onEnter" @clickoverlay="sku_popup.show = false">
		<view class="space-view">
			<!-- 展示已选的规格：图片，价格等-->
			<view class="space-price">
				<view class="space-goods-img">
					<image :src="goods.goods_cover" mode="aspectFill"></image>
				</view>
				<!-- 价格和库存 -->
				<view class="space-text">
					<view class="space-text-price">
						<text>{{goods.goods_price}}</text>
						<text v-if="Order.exist_seckill">秒杀价: ¥{{Order.order.goods_price}}</text>
					</view>
					<text class="space-text-stock">库存{{goods.stock}}</text>

					<!-- 如果选中规格，显示已选择 没有选择显示请选择 -->
					<view class="choice">
						<text>{{selectSku.length > 0 ? '已选择' : '请选择'}}</text>
						<!-- 请选择 ： 规格的名字 -->
						<text v-if="selectSku.length == 0" v-for="(item,index) in optionalSku" :key="index">{{item.att_name}}</text>
						<!-- 已选择 ： 牛奶味 378g 等等 -->
						<text v-else v-for="(item,index) in selectSku" :key="index">{{item.att_val}}</text>
					</view>
				</view>

				<!-- 关闭按钮 -->
				<view class="space-close" @click="sku_popup.show = false">
					<image src="/static/images/close.svg" mode="aspectFit"></image>
				</view>
			</view>

			<!-- sku选择区域-->
			<view class="space-margin">
				<block v-for="(item,index) in optionalSku" :key="index">
					<!-- 规格属性名 口味 -->
					<text class="space-title">{{item.att_name}}</text>
					<!-- 规格属性值 牛奶味等 -->
					<view class="space-sku">
						<text v-for="(item2,index2) in item.sku" :key="index2" :class="[item2.active ? 'prevent_style' : '', selectIndex[index] == index2 ? 'new_style' : '']"
							@click="choose(item.att_name,item2.att_val,index,index2)">
							{{item2.att_val}}
						</text>
					</view>
				</block>
			</view>

			<!-- 购买数量 -->
			<view class="purchasequantity">
				<view class="purchasetitle">购买数量</view>
				<view class="purchaseimage">
					<image src="/static/images/sub.png" mode="aspectFit" @click="sub" :class="[goods_amount == 1 ? 'prevent_style' : '']"></image>
					<text>{{goods_amount}}</text>
					<image src="/static/images/add.png" mode="aspectFit" @click="add"></image>
				</view>
			</view>

			<!-- 给一个防止超出页面的区域被按钮给盖住 -->
			<view style="height: 300rpx;"></view>

			<!-- 底部按钮 -->
			<view class="space-botton">
				<view @click="submit(sku_popup.option)">{{sku_popup.option == 'add-cart' ? '加入购物车' : '立即购买'}}</view>
			</view>

		</view>
	</page-container>
</template>

<script setup>
	// 详情页点击底部加购或购买拉起sku弹窗
	import { sku_popup, Order } from '@/public/package-js/passValue.js'
	import { defineProps, watch, reactive, toRefs, toRaw, nextTick, ref } from 'vue'
	import { FeedBack } from "@/public/package-js/feedBack.js"


	// 触发弹窗
	function onEnter() {}

	const props = defineProps({
		skuData: Array, // 规格数据
		goods: Object // 商品数据
	})

	const data = reactive({
		goods: {},
		optionalSku: [], // 用于展示页面供用户选择的规格
		all_sku: [], // 所有规格数据
		sku_length: 0, // 规格长度 用于判断是单规格还是多规格
		sku_sort: {}, // {口味: 0, 净含量: 1} 用来对用户已选择规格作排序的参考

		selectSku: [], //选中规格selectSku:[{att_name:'口味',att_val:'微辣'}]
		selectIndex: [], // 存放选中规格用以切换样式的下标 {0: 1, 1: 0}  表示选中第一个规格的第二个选项和第二个规格的第一个选项

		tempList: [], //存放没有排序前的已选择的规格
		goods_amount: 1, // 购买数量，默认最少为 1
	})
	const { goods, optionalSku, selectSku, selectIndex, goods_amount } = toRefs(data)

	// 1、监听父组件传值的变化进行显示规格操作
	watch(props, (newVal, oldVal) => {
		const newProps = JSON.parse(JSON.stringify(newVal)) //深拷贝
		// console.log("newProps", newProps);
		data.goods = newProps.goods

		// 1-1 如果没有规格就不操作
		if (newProps.skuData.length === 0) {
			return false
		}
		// 有规格，将规格数据取出来
		const skuData = newProps.skuData[0]

		// 取出sku数据，给后面的开发使用
		data.all_sku = skuData.sku
		// 取出规格属性长度，可以得出是单规格还是多规格
		data.sku_length = skuData.sku[0].attribute.length

		// 将规格属性的 属性名 以及 在 attribute 对应的下标 取出来
		skuData.sku[0].attribute.forEach((item, index) => {
			// 组装，用以查询多规格库存存对已选择规格按照 data.sku_sort 进行排序
			data.sku_sort = {
				...data.sku_sort,
				...{
					[item.att_name]: index
				}
			}
		})

		// console.log("data.sku_sort",data.sku_sort);

		// 1-2 取出规格属性标题
		const skuNameArr = skuData.sku[0].attribute.map(item => item.att_name)

		// 重组sku展示，根据skuNameArr有多少条而取出：判断是单规格（口味）还是多规格（口味、净含量）
		let optionalSku = []
		let skuAtt_length = skuData.sku[0].attribute.length //判断是单规格还是多规格
		for (let i = 0; i < skuNameArr.length; i++) {
			// 对 skuData.sku 每一项进行遍历操作，返回一个新数组
			let res = skuData.sku.map(item => {
				if (skuAtt_length == 1) { // 单规格
					return {
						att_val: item.attribute[i].att_val,
						stock: item.stock,
						active: item.stock == 0 ? true : false
					}
				} else { // 多规格
					return {
						att_val: item.attribute[i].att_val,
						active: false // 用于控制多规格库存为 0 时的禁止点击样式
					}
				}
			})

			// 数组对象去重，将多规格的属性名和属性值重复的去掉
			let obj = {}
			let newSku = res.reduce((prev, item) => {
				if (!obj[item.att_val]) {
					prev.push(item)
					obj[item.att_val] = true
				}
				return prev
			}, [])

			// 组装新的 可供选择的规格展示数组
			optionalSku.push({ att_name: skuNameArr[i], sku: newSku })
		}
		// console.log("Optional ", optionalSku);

		// 赋值，用以页面渲染
		data.optionalSku = optionalSku

	})

	// 2、点击规格切换颜色以及查询选中对应规格的价格、库存等
	function choose(att_name, att_val, index, index2) {

		//  2-1 切换选中样式
		let nIndex = data.selectSku.findIndex(item => item.att_name == att_name)

		// 如果点击的规格属性名（例如口味）已经被选择
		if (nIndex > -1) {
			// 查找选择的规格属性值是否已经存在 selectSku 里面
			let vIndex = data.selectSku.findIndex(item => item.att_val == att_val)
			if (vIndex > -1) {
				// 如果存在，就取消选择，删除数组中对应的项以及选中样式
				data.selectSku.splice(nIndex, 1)
				data.selectIndex[index] = -1 // 下标随意赋小于0的值
			} else {
				// 如果不存在，则将相同属性名（口味）的那一项替换成新选择的
				data.selectSku[nIndex].att_val = att_val

				// 并将选中样式下标替换（将选中的属性值的下标）
				data.selectIndex[index] = index2

			}

		} else { // 还未选择属性名
			// 将选择的规格属性名和属性值 push 进数组
			data.selectSku.push({ att_name, att_val })
			data.selectIndex[index] = index2
		}

		data.tempList = JSON.parse(JSON.stringify(data.selectSku))

		// 2-2 查询选中的sku的图片，价格，库存
		// 只有每一项 att_name 都有选择，才进行排序
		if (data.selectSku.length == data.sku_length) {
			// 对已选的sku排序，保证显示用户已选择时 第一项是 att_name 第二项是 att_value
			data.selectSku.sort((x, y) => {
				// sku_sort: {口味: 0, 净含量: 1} 
				return data.sku_sort[x.att_name] - data.sku_sort[y.att_name]
			})

			// console.log("data.all_sku.",data.all_sku);
			// console.log("data.selectSku", data.selectSku);

			// 在该商品所有规格，将与选中的属性相等的规格信息过滤出来
			let query_sku = data.all_sku.filter(item => {
				return JSON.stringify(item.attribute) == JSON.stringify(data.selectSku)
			})

			// console.log("query_sku", query_sku);
			// 对渲染列表进行赋值
			data.goods.goods_cover = query_sku[0].imgUrl
			data.goods.goods_price = query_sku[0].price
			data.goods.stock = query_sku[0].stock
		}

		// 2-3 查询库存是否不足:主要是多规格
		if (data.optionalSku.length == 1) {
			return false
		}

		// 将 data 响应式对象 转为普通数据
		let raw = toRaw(data)
		// console.log("raw",raw);


		// 2-4 将多规格中库存为 0 的选项禁止用户点击

		// 给所有规格数据增加一个自定义的标记字段，用于标记已选中且库存为 0 的规格
		raw.all_sku.forEach(item => item['mark'] = '')

		// console.log("data.selectSku",data.selectSku);

		// 对已选择规格和所有规格数据进行遍历，对已经选择规格并且库存为 0 的规格的 mark 进行改变
		data.selectSku.forEach((item, index) => {
			raw.all_sku.forEach((item2, index2) => {
				// 如果遍历到某个商品的库存为 0，就找该商品的规格
				if (item2.stock === 0) {
					// 遍历该库存为0的商品的规格属性
					item2.attribute.forEach((item3, index3) => {
						// 当规格属性名和属性值与已选择的相同的时候  {att_name:口味 att_val:微辣}
						if (item3.att_name === item.att_name && item3.att_val === item.att_val) {
							// mark 就标记为不是空字符串，将没有库存的规格属性名拼接至 mark 属性
							raw.all_sku[index2].mark += item3.att_val
						}
					})
				}
			})
		})

		// console.log("raw.all_sku", raw.all_sku);

		// // 定义一个新的字段用来提取用户选择的规格属性值
		let selectSkuVal = ''
		// 遍历选择的规格属性，将所选的规格属性值提取出来
		data.selectSku.forEach((item, index) => {
			selectSkuVal += item.att_val
		})

		let arr = []

		if (selectSkuVal == '') { // 没有选中或者选中后取消选中
			arr = []
		} else { //选中
			// 筛选出来的 选择的且库存为 0 的规格信息 赋值
			arr = raw.all_sku.filter(item => item.mark == selectSkuVal)
		}


		// console.log("arr", arr);
		// console.log("optionalSku",data.optionalSku);

		// 让库存为 0 的禁用点击，去掉背景颜色
		if (arr.length > 0) {
			// 遍历筛选出来的库存为 0 的 arr
			for (let i = 0; i < arr.length; i++) {
				// 遍历每一项 arr 的规格属性
				for (let j = 0; j < arr[i].attribute.length; j++) {
					// 遍历供用户可选择的规格数组
					for (let m = 0; m < data.optionalSku.length; m++) {
						// 遍历 optionalSku 数组的 sku [{att_val: "果味", active: false},{att_val: "牛奶味", active: false}]
						for (let n = 0; n < data.optionalSku[m].sku.length; n++) {
							// 遍历用户选择的规格数组
							data.selectSku.forEach(async (item, idnex) => {
								// 当用户选择对应库存为 0 的规格的属性的其中一项时 ：item.att_name != data.optionalSku[m].att_name
								// 比如 [{att_name:口味，att_val:微辣} ,{att_name:净含量，att_val:375g}] 库存为 0，
								// 选中微辣，那么库存为 0 的净含量的 375g 就不能被选中
								if (item.att_name != data.optionalSku[m].att_name && arr[i].attribute[j].att_val == data.optionalSku[m].sku[n].att_val) {
									await nextTick()
									// active 改为 true 就不能被点击
									data.optionalSku[m].sku[n].active = true

									// 让对应库存为 0 的（假如选择口味，就让对应净含量375g的选项没法选中）
									data.selectIndex[m] = -1

									// 查找选中的属性值 == 规格展示的属性值的下标
									let vIndex = data.selectSku.findIndex(item => item.att_val == data.optionalSku[m].sku[n].att_val)
									// 假如选择口味，就让对应净含量375g的选项从选中列表删除
									if (vIndex > -1) {
										data.selectSku.splice(vIndex, 1)
									}
								}
							})
						}
					}
				}
			}
		} else {
			// console.log("data.tempList", data.tempList);
			let isChange = true
			raw.all_sku.forEach((item, index) => {
				if (data.tempList.length > 0) {
					if (data.tempList[0].att_val == item.mark) {
						isChange = false
					}
				}
			})

			if (isChange) {
				// 库存不为 0 ，恢复样式
				data.optionalSku.forEach(async (item, index) => {
					await nextTick()
					item.sku.forEach((item2, index2) => {
						if (item2.active) {
							item2.active = false
						}
					})
				})
			}
		}
	}

	// 3、加减商品数量
	function sub() {
		if (data.selectSku.length == 0 && optionalSku.length != 0) {
			new FeedBack('请选择商品规格', 'none').toast()
		} else {
			data.goods_amount--
		}

	}

	function add() {
		if (data.selectSku.length == 0 && optionalSku.length != 0) {
			new FeedBack('请选择商品规格', 'none').toast()
		} else {
			// data.goods_amount++
			data.goods_amount >= data.goods.stock ? new FeedBack('商品库存不足', 'none').toast() : data.goods_amount++
		}

	}

	// 4、加入购物车或者直接下单
	async function submit(option) {
		if (data.selectSku.length != data.optionalSku.length) {
			new FeedBack("请选择商品规格", "error").toast()
		} else {
			// console.log("data.selectSku", data.selectSku);

			// 将动态的下单的商品信息赋值
			Order.order.buy_amount = data.goods_amount
			Order.order.specs = data.selectSku
			Order.order.goods_image = data.goods.goods_cover
			//  是否有秒杀，因为有秒杀的时候就赋值为秒杀价格了
			Order.order.goods_price = Order.exist_seckill ? Order.order.goods_price : data.goods.goods_price

			if (option == 'add-cart') {
				// 加入购物车
				const db = wx.cloud.database()

				// 查询购物车数据库商品是否有相同的规格
				let equal_sku = ''
				//有规格就遍历规格，给equal_sku赋值选中的规格
				if (Order.order.specs.length > 0) {
					// 遍历订单规格
					Order.order.specs.forEach(item => equal_sku += item.att_val)
					Order.order.equal_sku = equal_sku
				}
				// 判断数据库是否出现相同的数据
				let res = await db.collection('shopping_cart').where({
					goods_id: Order.order.goods_id,
					equal_sku
				}).get()

				if (res.data.length > 0) {
					// 有相同规格，向对应规格增加购买数量
					const _ = db.command
					await db.collection('shopping_cart').doc(res.data[0]._id).update({
						data: {
							buy_amount: _.inc(1)
						}
					})
					// 关闭规格弹窗
					sku_popup.show = false
				} else {
					console.log("Order", Order.order);

					// 没有相同规格，向购物车添加新的数据
					await db.collection('shopping_cart').add({
						data: {
							goods_id: Order.order.goods_id,
							goods_image: Order.order.goods_image,
							goods_title: Order.order.goods_title,
							goods_price: Order.order.goods_price,
							buy_amount: Order.order.buy_amount,
							specs: Order.order.specs,
							equal_sku: Order.order.equal_sku,
							add_time: new Date().getTime()
						}
					})
					Order.shop_cart_num += 1
					sku_popup.show = false
				}
				new FeedBack("加入购物车成功", "success").toast()
			} else {
				/* 立即购买 */
				// 计算总价进行赋值
				Order.order.subtotal = parseFloat(Order.order.goods_price * Order.order.buy_amount)
				sku_popup.show = false
				//  将订单信息转为数组 传递到确认订单界面
				const order = JSON.stringify([Order.order])
				uni.navigateTo({ //type=direct 表示单个商品直接购买下单
					url: `/pages/confirm-order/confirm-order?order=${order}&type=direct`
				})

			}
		}
	}
</script>

<style scoped>
	.space-goods-img {
		width: 180rpx;
		height: 180rpx;
	}

	.space-goods-img image {
		width: 180rpx;
		height: 180rpx;
		border-radius: 10rpx;
	}

	.space-close {
		width: 30rpx;
		height: 30rpx;
	}

	.space-close image {
		width: 30rpx;
		height: 30rpx;
	}

	.space-price {
		display: flex;
		border-bottom: 1rpx solid #ececed;
		padding-bottom: 20rpx;
	}

	.space-price text {
		display: block;
	}

	.space-text {
		flex: 1;
		align-self: flex-end;
		padding: 0 20rpx;
		font-size: 26rpx;
	}

	.space-text-price {
		display: flex;
		align-items: center;
	}

	.space-text-price text:nth-child(1) {
		color: #e9445a;
		font-size: 40rpx;
	}

	.space-text-price text:nth-child(2) {
		font-size: 30rpx;
		background-color: #e9445a;
		color: #ffffff;
		border-radius: 40rpx;
		padding: 10rpx;
		margin-left: 20rpx;
	}

	.space-text-stock {
		padding: 8rpx 0;
		color: #8d8e92;
	}

	.choice {
		display: flex;
		align-items: center;
		color: #8d8e92;
		/* flex-wrap: wrap; */
	}

	.choice text:nth-child(1) {
		width: 100rpx;
		color: #333333 !important;
	}

	.choice text:nth-child(2) {
		overflow: hidden;
		white-space: nowrap;
		text-overflow: ellipsis;
		margin-right: 10rpx;
	}

	.space-margin {
		margin: 20rpx 0;
		border-bottom: 1rpx solid #ececed;
	}

	.space-title {
		margin-bottom: 20rpx;
		display: block;
		font-weight: bold;
	}

	.space-sku {
		display: flex;
		flex-wrap: wrap;
	}

	.space-sku text {
		font-size: 28rpx;
		background-color: #f8f8f8;
		padding: 10rpx 20rpx;
		margin: 0 20rpx 20rpx 0;
		border-radius: 8rpx;
	}

	.purchasequantity image {
		width: 50rpx;
		height: 50rpx;
		display: block;
	}

	.purchasequantity {
		display: flex;
		align-items: center;
		justify-content: space-between;
	}

	.purchasetitle {
		font-weight: bold;
	}

	.purchaseimage {
		display: flex;
		align-items: center;
	}

	.purchaseimage text {
		padding: 0 40rpx;
	}

	.space-botton {
		background-color: #fefefe;
		height: 150rpx;
		position: fixed;
		bottom: 0;
		left: 0;
		right: 0;
	}

	.space-botton view {
		height: 80rpx;
		text-align: center;
		line-height: 80rpx;
		color: #FFFFFF;
		background-color: #e9445a;
		margin: 10rpx 20rpx;
		border-radius: 6rpx;
	}

	/* 点击后加上新样式 */
	.new_style {
		background-color: #e9445a !important;
		color: #FFFFFF;
	}
</style>
